<?php
/**
 * 生成随机字符串
 * @param integer $num 生成字符串的长度
 * @return string       返回生成的随机字符串
 */
function get_random_str($num = 8)
{
    $pattern = 'AaZzBb0YyCc9XxDd8Ww7EeVvF6fUuG5gTtHhS4sIiRr3JjQqKkP2pLlO1oMmNn';
    $str = '';
    for ($i = 0; $i < $num; $i++) {
        $str .= $pattern{mt_rand(0, 35)}; //生成 php 随机数
    }
    return $str;
}

/**
 * 生成随机数字串
 * @author 贺强
 * @time   2018-11-05 15:14:37
 * @param integer $num 要生成数字串的长度
 * @return string       返回生成的数字串
 */
function get_random_num($num = 6)
{
    $pattern = '9482135706';
    $str = '';
    for ($i = 0; $i < $num; $i++) {
        $str .= $pattern{mt_rand(0, 9)}; //生成 php 随机数
    }
    return $str;
}

/**
 * 获取外网 ip
 * @author 贺强
 * @time   2020-06-23 17:11:59
 */
function getIp()
{
    if (isset($_SERVER)) {
        if (isset($_SERVER["HTTP_X_FORWARDED_FOR"])) {
            $realip = $_SERVER["HTTP_X_FORWARDED_FOR"];
        } else {
            if (isset($_SERVER["HTTP_CLIENT_IP"])) {
                $realip = $_SERVER["HTTP_CLIENT_IP"];
            } else {
                $realip = $_SERVER["REMOTE_ADDR"];
            }
        }
    } else {
        if (getenv("HTTP_X_FORWARDED_FOR")) {
            $realip = getenv("HTTP_X_FORWARDED_FOR");
        } else {
            if (getenv("HTTP_CLIENT_IP")) {
                $realip = getenv("HTTP_CLIENT_IP");
            } else {
                $realip = getenv("REMOTE_ADDR");
            }
        }
    }
    return $realip;
}

/**
 * 格式化日期或时间
 * @author 贺强
 * @time   2019-11-20 14:01:08
 * @param string  $datetime 要格式化的日期或时间
 * @param integer $flag     格式化后类型，1-日期+时间 2-时间戳 3-多久前
 */
function format_datetime(&$datetime, $flag = 1)
{
    if ($flag === 1) {
        $datetime = date('Y-m-d H:i:s', $datetime);
    } elseif ($flag === 2) {
        $datetime = strtotime($datetime);
    } elseif ($flag === 3) {
        $diff = time() - $datetime;
        if ($diff < 10) {
            $datetime = '刚刚';
        } elseif ($diff < 60) {
            $datetime = $diff . '秒前';
        } elseif ($diff < 3600) {
            $datetime = intval($diff / 60) . '分钟前';
        } elseif ($diff < 24 * 3600) {
            $datetime = intval($diff / 3600) . '小时前';
        } elseif ($diff < 30 * 24 * 3600) {
            $datetime = intval($diff / (24 * 3600)) . '天前';
        } elseif ($diff < 365 * 24 * 3600) {
            $datetime = intval(di / (30 * 24 * 3600)) . '个月前';
        } elseif ($diff < 3652 * 24 * 3600) {
            $datetime = intval($diff / (3652 * 24 * 3600)) . '年前';
        } else {
            $datetime = datetime('Y-m-d H:i:s');
        }
        // if ($diff > 3652 * 24 * 3600) {
        //     $datetime = date('Y-m-d H:i:s', $datetime);
        // } elseif ($diff > 365 * 24 * 3600) {
        //     $datetime = intval($diff / (365 * 24 * 3600)) . '年前';
        // } elseif ($diff > 30 * 24 * 3600) {
        //     $datetime = intval($diff / (30 * 24 * 3600)) . '个月前';
        // } elseif ($diff > 24 * 3600) {
        //     $datetime = intval($diff / (24 * 3600)) . '天前';
        // } elseif ($diff > 3600) {
        //     $datetime = intval($diff / 3600) . '小时前';
        // } elseif ($diff > 60) {
        //     $datetime = intval($diff / 60) . '分钟前';
        // } else {
        //     $datetime = '刚刚';
        // }
    }
    return $datetime;
}

/**
 * 获取毫秒
 * @author 贺强
 * @time   2019-06-29 14:26:45
 * @param boolean $time 是否添加当前时间
 */
function get_millisecond()
{
    [$microsecond, $time] = explode(' ', microtime()); //' '中间是一个空格
    // 毫秒
    $hm = (float)sprintf('%.0f', (floatval($microsecond) + floatval($time)) * 1000);
    return $hm;
}

/**
 * 生成密码
 * @param string $str 明文密码
 * @return string       返回加密后的密码
 */
function get_password($str)
{
    $pwd = password_hash($str, PASSWORD_DEFAULT);
    return $pwd;
}

/**
 * 按字节数截取字符串
 * @author 贺强
 * @time   2021-03-17 16:25:57
 * @param string  $str    要截取的字符串
 * @param integer $length 截取长度
 * @return string          返回截取后的字符串
 */
function esubstr($str, $length = 0, $suffix = '')
{
    // 如果截取长度小于 1 则直接返回原字符串
    if ($length < 1) {
        return $str;
    }
    $str = mb_substr($str, 0, $length) . $suffix;
    return $str;
}

/**
 * 获取客户端IP
 * @author 贺强
 * @time   2018-11-13 10:05:32
 * @return string 返回获取的IP
 */
function get_client_ip()
{
    // 判断服务器是否允许$_SERVER
    if (isset($_SERVER)) {
        if (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) {
            $realip = $_SERVER['HTTP_X_FORWARDED_FOR'];
        } elseif (isset($_SERVER['HTTP_CLIENT_IP'])) {
            $realip = $_SERVER['HTTP_CLIENT_IP'];
        } else {
            $realip = $_SERVER['REMOTE_ADDR'];
        }
    } else {
        //不允许就使用getenv获取
        if (getenv('HTTP_X_FORWARDED_FOR')) {
            $realip = getenv('HTTP_X_FORWARDED_FOR');
        } elseif (getenv('HTTP_CLIENT_IP')) {
            $realip = getenv('HTTP_CLIENT_IP');
        } else {
            $realip = getenv('REMOTE_ADDR');
        }
    }
    return $realip;
}

/**
 * 数组转 xml
 * @author 贺强
 * @time   2018-11-13 15:03:03
 * @param array $arr 被转换的数组
 * @return string      返回转换后的 xml 字符串
 */
function array2xml($arr, $root = true)
{
    $xml = "";
    if ($root) {
        $xml = "<xml>";
    }
    foreach ($arr as $key => $val) {
        if (is_array($val)) {
            $child = array2xml($val, false);
            $xml .= "<$key><![CDATA[$child]]></$key>";
        } else {
            $xml .= "<$key><![CDATA[$val]]></$key>";
        }
    }
    if ($root) {
        $xml .= "</xml>";
    }
    return $xml;
}

/**
 * xml 转换为数组
 * @author 贺强
 * @time   2018-11-13 15:12:04
 * @param string $xml 被转换的 xml
 * @return array       返回转换后的数组
 */
function xml2array($xml)
{
    libxml_disable_entity_loader(true);
    $values = json_decode(json_encode(simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA)), true);
    return $values;
}

/**
 * 输出 json 字符串
 * @author 贺强
 * @time   2021-06-01 12:03:04
 * @param integer $code     状态
 * @param string  $msg      返回的消息
 * @param array   $data     返回数据
 * @param string  $callback 是否是 jsonp 格式数据
 */
function ejson($code = 200, $msg = '', $data = [], $callback = '')
{
    if ($callback) {
        return $callback . '(' . json_encode(['code' => $code, 'msg' => $msg, 'data' => $data, 'callback' => $callback]) . ')';
    }
    return json_encode(['code' => $code, 'msg' => $msg, 'data' => $data]);
}

/**
 * 返回 ajax 数据
 * @author 贺强
 * @time   2021-06-01 13:36:15
 * @param integer $code     状态
 * @param string  $msg      返回的消息
 * @param array   $data     返回数据
 * @param string  $callback 是否是 jsonp 格式数据
 */
function ajax($code = 200, $msg = '', $data = [], $callback = '')
{
    if ($callback) {
        return $callback . '(' . json_encode(['code' => $code, 'msg' => $msg, 'data' => $data, 'callback' => $callback]) . ')';
    }
    return json(['code' => $code, 'msg' => $msg, 'data' => $data]);
}

/**
 * 格式化数字
 * @author 贺强
 * @time   2018-11-30 16:12:39
 * @param integer $num  要格式化的数字
 * @param string  $unit 单位
 * @return string       返回格式化后的字符串
 */
function format_number($num = 0, $unit = '万')
{
    $arr = [
        '万' => 10000,
        '十万' => 100000,
        '百万' => 1000000,
        '千万' => 10000000,
        '亿' => 100000000,
    ];
    $divisor = $arr[$unit] ?? 1;
    $num = bcdiv($num, $divisor, 2) . $unit;
    return $num;
}

/**
 * 格式化金额
 * @author 贺强
 * @time   2022/3/17 15:54
 * @param int    $money 要格式化的金额
 * @param string $unit  单位 千(K) 万(W) 百万(M)
 * @return string       返回格式化后的字符串
 */
function format_money($money = 0, $unit = 'K')
{
    $arr = [
        'K' => 1000,
        'W' => 10000,
        'M' => 1000000,
    ];
    $divisor = $arr[$unit] ?? 1;
    $money = bcdiv($money, $divisor, 2) . $unit;
    return $money;
}

/**
 * 格式化数据
 * @author 贺强
 * @time   2021-04-14 14:20:00
 * @param int    $nubmer  格式化数据
 * @param string $unit    格式化之后的单位
 * @param string $divisor 除数
 * @return int|string 字符串
 */
function format_number_myriad($nubmer = 0, $unit = '万', $divisor = 1000)
{
    if ($divisor > 0) {
        $nubmer = number_format($nubmer / $divisor, 2, ".", "") . $unit;
    }
    return $nubmer;
}

/**
 * 计算两点地理坐标之间的距离
 * @param decimal $longitude1 起点经度
 * @param decimal $latitude1  起点纬度
 * @param decimal $longitude2 终点经度
 * @param decimal $latitude2  终点纬度
 * @param int     $unit       单位 1:米 2:公里
 * @param int     $decimal    精度 保留小数位数
 * @return decimal
 */
function getDistance($longitude1, $latitude1, $longitude2, $latitude2, $unit = 1, $decimal = 0)
{
    $EARTH_RADIUS = 6370.996; // 地球半径系数
    $PI = 3.1415926;
    $radLat1 = $latitude1 * $PI / 180.0;
    $radLat2 = $latitude2 * $PI / 180.0;
    $radLng1 = $longitude1 * $PI / 180.0;
    $radLng2 = $longitude2 * $PI / 180.0;
    $a = $radLat1 - $radLat2;
    $b = $radLng1 - $radLng2;
    $distance = 2 * asin(sqrt(pow(sin($a / 2), 2) + cos($radLat1) * cos($radLat2) * pow(sin($b / 2), 2)));
    $distance = $distance * $EARTH_RADIUS * 1000;
    if ($unit === 2) {
        $distance = $distance / 1000;
    }
    return round($distance, $decimal);
}

/**
 * 获取具体位置
 * @author 贺强
 * @time   2019-01-16 09:22:55
 * @param float $lat 纬度
 * @param float $lng 经度
 * @return string      返回位置信息
 */
function getRealyAddress($lat, $lng)
{
    $address = '';
    if ($lat && $lng) {
        $arr = changeToBaidu($lat, $lng);
        $url = 'http://api.map.baidu.com/geocoder/v2/?callback=&location=' . $arr['y'] . ',' . $arr['x'] . '.&output=json&pois=1&ak=fKvpmBXsoCcx8AMGqOThmd2ZEXHpniVq';
        $content = file_get_contents($url);
        $place = json_decode($content, true);
        $address = $place['result']['formatted_address'];
    }
    return $address;
}

/**
 * 转换为百度经纬度
 * @author 贺强
 * @time   2019-01-16 09:21:52
 * @param float $lat 纬度
 * @param float $lng 经度
 * @return float      百度经纬度
 */
function changeToBaidu($lat, $lng)
{
    $apiurl = 'http://api.map.baidu.com/geoconv/v1/?coords=' . $lng . ',' . $lat . '&from=1&to=5&ak=fKvpmBXsoCcx8AMGqOThmd2ZEXHpniVq';
    $file = file_get_contents($apiurl);
    $arrpoint = json_decode($file, true);
    return $arrpoint['result'][0];
}

/**
 * 获取地理位置信息
 * @author 贺强
 * @time   2019-01-05 10:35:18
 * @param string $latlng 经纬度
 * @param string $place  要获取的信息,all/location/formatted_address/city/province/district/direction/distance/street/street_number
 * @param string $type   返回数据格式
 */
function getAddressInfo($latlng, $place = 'all', $type = 'json')
{
    $url = "http://api.map.baidu.com/geocoder?location=30.990998,103.645966&output=json&key=28bcdd84fae25699606ffad27f8da77b";
    $url = "http://api.map.baidu.com/geocoder?location={$latlng}&output={$type}&key=28bcdd84fae25699606ffad27f8da77b";
    $info = file_get_contents($url);
    if ($place === 'all') {
        return $info;
    } else {
        $info = json_decode($info, true);
        $info = $info['result'];
        if ($place === 'location' || $place === 'formatted_address') {
            if (empty($info[$place])) {
                return '';
            }
            return $info[$place];
        } else {
            $info = $info['addressComponent'];
            if (empty($info[$place])) {
                return '';
            }
            return $info[$place];
        }
    }
}

/**
 * 获取视频文件的缩略图
 * @author 贺强
 * @time   2019-01-16 09:47:14
 * @param string  $file   视频文件路径
 * @param integer $s      指定从什么时间开始截取，单位秒
 * @param boolean $is_win 是否是 windows 系统
 * @return string          返回截取的图片保存路径
 */
function getVideoCover($file, $s = 11, $is_win = false)
{
    $ffmpeg = '/monchickey/ffmpeg/bin/ffmpeg';
    $root = ROOT_PATH . 'public';
    if ($is_win) {
        $ffmpeg = 'D:/ffmpeg/ffmpeg.exe';
    }
    $path = '/uploads/cli/video/' . date('Y') . '/' . date('m') . '/' . date('d');
    if (!is_dir($root . $path)) {
        @mkdir($root . $path, 0755, true);
    }
    $path .= '/' . get_millisecond() . '.jpg';
    // $strlen = strlen($file);
    $str = "{$ffmpeg} -i {$file} -ss {$s} {$root}{$path}";
    system($str);
    return $path;
}

/**
 * 得到转换编码后的拼音
 * @author 贺强
 * @time   2019-01-25 17:27:22
 * @param string  $s       要得到拼音的文字
 * @param boolean $isfirst 是否只获取拼音首字母
 * @return string           返回获取的拼音
 */
function utf8_to($s, $isfirst = false)
{
    return get_pinying(utf8_to_gb2312($s), $isfirst);
}

/**
 * UTF8转换为BG2312编码
 * @author 贺强
 * @time   2019-01-25 17:26:00
 * @param string $s 要转换编码的文字
 * @return string    返回转换编码后的文字
 */
function utf8_to_gb2312($s)
{
    return iconv('UTF-8', 'GB2312//IGNORE', $s);
}

/**
 * 获取汉字拼音
 * @author 贺强
 * @time   2019-01-24 17:34:19
 * @param string  $s       要获取拼音的汉字
 * @param boolean $isfirst 是否只获取每个字的首字母
 * @return string           返回获取到的拼音
 */
function get_pinying($s, $isfirst = false)
{
    $res = '';
    $len = strlen($s);
    $pinyin_arr = get_pinyin_array();
    for ($i = 0; $i < $len; $i++) {
        $ascii = ord($s{$i});
        if ($ascii > 0x80) {
            $ascii2 = ord($s{++$i});
            $ascii = $ascii * 256 + $ascii2 - 65536;
        }
        if ($ascii < 255 && $ascii > 0) {
            if (($ascii >= 48 && $ascii <= 57) || ($ascii >= 97 && $ascii <= 122)) {
                $res .= $s{$i}; // 0-9 a-z
            } elseif ($ascii >= 65 && $ascii <= 90) {
                $res .= strtolower($s{$i}); // A-Z
            } else {
                $res .= '_'; ////将符号转义 不替换符号$res .= $s{$i};
            }
        } elseif ($ascii < -20319 || $ascii > -10247) {
            $res .= '_';
        } else {
            foreach ($pinyin_arr as $py => $asc) {
                if ($asc <= $ascii) {
                    $res .= $isfirst ? $py{0} : $py;
                    break;
                }
            }
        }
    }
    return $res;
}

/**
 * 获取汉字的首字母
 * @author 贺强
 * @time   2019-01-24 17:37:19
 * @param string $s 要获取首字母的汉字
 * @return string    返回获取到的首字母
 */
function get_first($s)
{
    $ascii = ord($s{0});
    if ($ascii > 0xE0) {
        $s = utf8_to_gb2312($s{0} . $s{1} . $s{2});
    } elseif ($ascii < 0x80) {
        if ($ascii >= 65 && $ascii <= 90) {
            return strtolower($s{0});
        } elseif ($ascii >= 97 && $ascii <= 122) {
            return $s{0};
        } else {
            return false;
        }
    }
    if (strlen($s) < 2) {
        return false;
    }
    $asc = ord($s{0}) * 256 + ord($s{1}) - 65536;
    if ($asc >= -20319 && $asc <= -20284) {
        return 'a';
    }
    if ($asc >= -20283 && $asc <= -19776) {
        return 'b';
    }
    if ($asc >= -19775 && $asc <= -19219) {
        return 'c';
    }
    if ($asc >= -19218 && $asc <= -18711) {
        return 'd';
    }
    if ($asc >= -18710 && $asc <= -18527) {
        return 'e';
    }
    if ($asc >= -18526 && $asc <= -18240) {
        return 'f';
    }
    if ($asc >= -18239 && $asc <= -17923) {
        return 'g';
    }
    if ($asc >= -17922 && $asc <= -17418) {
        return 'h';
    }
    if ($asc >= -17417 && $asc <= -16475) {
        return 'j';
    }
    if ($asc >= -16474 && $asc <= -16213) {
        return 'k';
    }
    if ($asc >= -16212 && $asc <= -15641) {
        return 'l';
    }
    if ($asc >= -15640 && $asc <= -15166) {
        return 'm';
    }
    if ($asc >= -15165 && $asc <= -14923) {
        return 'n';
    }
    if ($asc >= -14922 && $asc <= -14915) {
        return 'o';
    }
    if ($asc >= -14914 && $asc <= -14631) {
        return 'p';
    }
    if ($asc >= -14630 && $asc <= -14150) {
        return 'q';
    }
    if ($asc >= -14149 && $asc <= -14091) {
        return 'r';
    }
    if ($asc >= -14090 && $asc <= -13319) {
        return 's';
    }
    if ($asc >= -13318 && $asc <= -12839) {
        return 't';
    }
    if ($asc >= -12838 && $asc <= -12557) {
        return 'w';
    }
    if ($asc >= -12556 && $asc <= -11848) {
        return 'x';
    }
    if ($asc >= -11847 && $asc <= -11056) {
        return 'y';
    }
    if ($asc >= -11055 && $asc <= -10247) {
        return 'z';
    }
    return false;
}

/**
 * 得到拼音和ASCII码数组
 * @author 贺强
 * @time   2019-01-24 17:39:37
 * @return array 返回得到的数组
 */
function get_pinyin_array()
{
    $py_arr = config('app.PY');
    arsort($py_arr);
    return $py_arr;
}

/**
 * URL 请求
 * @author 贺强
 * @time   2019-05-28 13:53:59
 * @param string $url    请求地址
 * @param string $post   POST 数据
 * @param array  $header 请求头
 * @param array  $cert   证书路径
 * @return object          返回请求返回的数据
 */
function curl_zs($url, $post = '', $header = [], $cert = [])
{
    $ch = curl_init();
    //超时时间
    curl_setopt($ch, CURLOPT_TIMEOUT, 300);
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
    curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
    //设置header
    if (empty($header)) {
        curl_setopt($ch, CURLOPT_HEADER, false);
    } else {
        curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
    }
    if (!empty($_SERVER['HTTP_USER_AGENT'])) {
        curl_setopt($ch, CURLOPT_USERAGENT, $_SERVER['HTTP_USER_AGENT']);
    }
    if (!empty($cert)) {
        if (is_array($cert)) {
            curl_setopt($ch, CURLOPT_SSLCERT, $cert['cert_url']);
            curl_setopt($ch, CURLOPT_SSLKEY, $cert['cert_key_url']);
        } else {
            curl_setopt($ch, CURLOPT_SSLCERT, $cert);
        }
    }
    //要求结果为字符串且输出到屏幕上
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    //post提交方式
    curl_setopt($ch, CURLOPT_POST, true);
    curl_setopt($ch, CURLOPT_POSTFIELDS, $post);
    $data = curl_exec($ch);
    //返回结果
    if ($data) {
        curl_close($ch);
        return $data;
    } else {
        $error = curl_errno($ch);
        echo "curl出错，错误码:$error" . "<br>";
        curl_close($ch);
        return false;
    }
}

/**
 * URL 请求
 * @author 贺强
 * @time   2019-05-28 13:53:59
 * @param string $url 请求地址
 * @return object     返回请求返回的数据
 */
function curl($url)
{
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
    $data = curl_exec($ch);
    curl_close($ch);
    //返回结果
    if ($data) {
        return $data;
    } else {
        $error = curl_errno($ch);
        echo "curl出错，错误码:$error" . "<br>";
        return false;
    }
}

/**
 * 使用异步方式请求远程URL
 * @author 贺强
 * @time   2019-05-28 17:47:29
 * @param string $url       要请求的URL
 * @param array  $data      请求参数
 * @param string $post_type 请求方式
 */
function curl_asyn($url, $data = [], $post_type = 'form', $extends = '')
{
    if ($post_type == 'json') {
        //以json的方式传输数据
        $data = json_encode($data);
        $content_type = 'application/json';
    } else {
        //以form表单的方式传输数据
        $data = http_build_query($data);
        $content_type = 'application/x-www-form-urlencoded';
    }
    $len = strlen($data);
    $url_array = parse_url($url);
    if (!isset($url_array['port'])) {
        $fp = fsockopen($url_array['host'], 80, $errno, $errstr, 3);
    } else {
        $fp = fsockopen($url_array['host'], $url_array['port'], $errno, $errstr, 3);
    }
    if ($fp) {
        $out = "POST {$url_array['path']} HTTP/1.1\r\n";
        $out .= "Host: {$url_array['host']}\r\n";
        $out .= "Content-type: $content_type\r\n";
        if (!empty($extends)) {
            $out .= ($extends . "\r\n");
        }
        $out .= "Content-Length: $len\r\n";
        $out .= "Connection: close\r\n";
        $out .= "\r\n";
        $out .= $data . "\r\n";
        fwrite($fp, $out);
        /* 实现异步把下面注释掉，意思是不处理返回,如要查看返回结果可打开注释start */
        //echo fread($fp, 1024);
        /* end */
        usleep(100);
        fclose($fp);
    }
}

/**
 * 同步 URL 请求
 * @author 贺强
 * @time   2019-05-31 10:30:26
 * @param string  $url     请求的 URL
 * @param string  $params  传递的参数
 * @param string  $method  请求方式
 * @param array   $header  传递的头部参数
 * @param integer $expire  超时时间
 * @param array   $options CURL 参数
 * @return array|string     返回请求结果
 */
function curl_sync($url, $params = '', $method = 'GET', $header = [], $expire = 30, $options = [])
{
    $cookieFile = env('runtime_path') . 'temp/' . md5(time()) . '.txt';
    $userAgent = !empty($_SERVER['HTTP_USER_AGENT']) ? $_SERVER['HTTP_USER_AGENT'] : 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.94 Safari/537.36';
    $ch = curl_init();
    $opt = [];
    // 请求参数
    $opt[CURLOPT_COOKIEJAR] = $cookieFile;
    $opt[CURLOPT_COOKIEFILE] = $cookieFile;
    $opt[CURLOPT_USERAGENT] = $userAgent;
    $opt[CURLOPT_CONNECTTIMEOUT] = $expire;
    $opt[CURLOPT_TIMEOUT] = $expire;
    $opt[CURLOPT_HTTPHEADER] = $header ?: ['Expect:'];
    $opt[CURLOPT_FOLLOWLOCATION] = true;
    $opt[CURLOPT_RETURNTRANSFER] = true;
    if (substr($url, 0, 8) == 'https://') {
        $opt[CURLOPT_SSL_VERIFYPEER] = false;
        $opt[CURLOPT_SSL_VERIFYHOST] = 2;
    }
    if (is_array($params) && $method === 'GET') {
        $params = http_build_query($params);
    } elseif (is_array($params) && $method === 'POST') {
        $params = json_encode($params);
    }
    switch (strtoupper($method)) {
        case 'GET':
            $extStr = (strpos($url, '?') !== false) ? '&' : '?';
            $url = $url . (($params) ? $extStr . $params : '');
            $opt[CURLOPT_URL] = $url . '?' . $params;
            break;
        case 'POST':
            $opt[CURLOPT_POST] = true;
            $opt[CURLOPT_POSTFIELDS] = $params;
            $opt[CURLOPT_URL] = $url;
            break;
        case 'PUT':
            $opt[CURLOPT_CUSTOMREQUEST] = 'PUT';
            $opt[CURLOPT_POSTFIELDS] = $params;
            $opt[CURLOPT_URL] = $url;
            break;
        case 'DELETE':
            $opt[CURLOPT_CUSTOMREQUEST] = 'DELETE';
            $opt[CURLOPT_POSTFIELDS] = $params;
            $opt[CURLOPT_URL] = $url;
            break;
        default:
            return ['error' => 0, 'msg' => '请求的方法不存在', 'info' => []];
            break;
    }
    curl_setopt_array($ch, (array)$opt + $options);
    $result = curl_exec($ch);
    $error = curl_error($ch);
    if ($result == false || !empty($error)) {
        $errno = curl_errno($ch);
        $info = curl_getinfo($ch);
        curl_close($ch);
        return [
            'errno' => $errno,
            'msg' => $error,
            'info' => $info,
        ];
    }
    curl_close($ch);
    return $result;
}

/**
 * 导出excel表格
 * @author 贺强
 * @time   2021-03-17 14:06:03
 * @param array $list   表格数据
 * @param array $params 表格列
 */
function excel_export($list, $params)
{
    $path = dirname(__FILE__); //找到当前脚本所在路径
    require_once '../extend/PHPExcel/PHPExcel.php';
    $PHPExcel = new \PHPExcel(); //实例化
    $PHPSheet = $PHPExcel->getActiveSheet();
    $PHPSheet->setTitle($params['title']); //给当前活动sheet设置名称
    //行数
    $rownum = 1;
    //标题
    foreach ($params['columns'] as $key => $column) {
        $PHPSheet->setCellValue(column($key, $rownum), $column['title']);
        if (!empty($column['width'])) {
            $PHPSheet->getColumnDimension(column_str($key))->setWidth($column['width']);
        }
    }
    $rownum++;
    //数据
    $len = count($params['columns']);
    foreach ($list as $row) {
        for ($i = 0; $i < $len; $i++) {
            $value = isset($row[$params['columns'][$i]['field']]) ? $row[$params['columns'][$i]['field']] : '';
            $PHPSheet->setCellValue(column($i, $rownum), $value);
        }
        $rownum++;
    }
    $filename = urlencode($params['title'] . '-' . date('Y-m-d H:i:s'));
    $PHPWriter = \PHPExcel_IOFactory::createWriter($PHPExcel, "Excel2007");      //创建生成的格式
    header('Content-Disposition: attachment;filename="' . $filename . '.xlsx"'); //下载下来的表格名
    header('Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
    $PHPWriter->save("php://output"); //表示在$path路径下面生成demo.xlsx文件
}

function column_str($key)
{
    $array = [
        'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
        'AA', 'AB', 'AC', 'AD', 'AE', 'AF', 'AG', 'AH', 'AI', 'AJ', 'AK', 'AL', 'AM', 'AN', 'AO', 'AP', 'AQ', 'AR', 'AS', 'AT', 'AU', 'AV', 'AW', 'AX', 'AY', 'AZ',
        'BA', 'BB', 'BC', 'BD', 'BE', 'BF', 'BG', 'BH', 'BI', 'BJ', 'BK', 'BL', 'BM', 'BN', 'BO', 'BP', 'BQ', 'BR', 'BS', 'BT', 'BU', 'BV', 'BW', 'BX', 'BY', 'BZ',
        'CA', 'CB', 'CC', 'CD', 'CE', 'CF', 'CG', 'CH', 'CI', 'CJ', 'CK', 'CL', 'CM', 'CN', 'CO', 'CP', 'CQ', 'CR', 'CS', 'CT', 'CU', 'CV', 'CW', 'CX', 'CY', 'CZ',
        'DA', 'DB', 'DC', 'DD', 'DE', 'DF', 'DG', 'DH', 'DI', 'DJ', 'DK', 'DL', 'DM', 'DN', 'DO', 'DP', 'DQ', 'DR', 'DS', 'DT', 'DU', 'DV', 'DW', 'DX', 'DY', 'DZ',
        'EA', 'EB', 'EC', 'ED', 'EE', 'EF', 'EG', 'EH', 'EI', 'EJ', 'EK', 'EL', 'EM', 'EN', 'EO', 'EP', 'EQ', 'ER', 'ES', 'ET', 'EU', 'EV', 'EW', 'EX', 'EY', 'EZ',
    ];
    return $array[$key];
}

function column($key, $columnnum = 1)
{
    return column_str($key) . $columnnum;
}

// 具体项目业务方法
/**
 * 把书籍状态转换成功文字描述
 * @author 贺强
 * @time   2021-03-01 14:19:43
 * @param integer $status 书籍状态
 * @return string          返回状态描述
 */
function get_book_status($status = 0)
{
    $status_arr = [
        0 => '未审核',
        1 => '已审核',
        2 => '已驳回',
    ];
    $status_txt = $status_arr[$status] ?? '未审核';
    return $status_txt;
}

/**
 * 书籍连载状态
 * @author 贺强
 * @time   2021-03-17 14:21:16
 * @param integer $status 连载状态
 * @return string          返回连载状态描述
 */
function get_serial_status($status = 0)
{
    $status_arr = [
        1 => '已完成',
    ];
    $status_txt = $status_arr[$status] ?? '连载中';
    return $status_txt;
}

/**
 * 书籍签约状态
 * @author 贺强
 * @time   2021-03-17 14:14:03
 * @param integer $status 签约状态
 * @return string          返回签约状态描述
 */
function get_sign_status($status = 0)
{
    $status_arr = [
        0 => '未签约',
        1 => '已签约',
        2 => '申请签约',
    ];
    $status_txt = $status_arr[$status] ?? '未签约';
    return $status_txt;
}

/**
 * 把客服状态转换成功文字描述
 * @author 贺强
 * @time   2021-10-03 16:18:21
 * @param integer $status 客服状态
 * @return string          返回状态描述
 */
function get_kefu_status($status = -1)
{
    $status_arr = [
        1 => '可用',
        4 => '不可用',
    ];
    $status_txt = $status_arr[$status] ?? '';
    return $status_txt;
}

/**
 * 把用户状态转换成文字描述
 * @author 贺强
 * @time   2019-06-10 17:03:37
 * @param integer $status 用户状态
 * @return string          返回状态描述
 */
function get_user_status($status = 0)
{
    $status_arr = [
        1 => '正常',
        4 => '禁用',
    ];
    $status_txt = $status_arr[$status] ?? '';
    return $status_txt;
}

/**
 * 把借款状态转换成文字描述
 * @author 贺强
 * @time   2021-09-26 14:52:31
 * @param string $status 借款状态
 * @return string         返回状态描述
 */
function get_loan_status($status = '')
{
    $status_arr = [
        1 => '待审核',
        2 => '已审核',
        4 => '已驳回',
    ];
    $status_txt = $status_arr[$status] ?? '';
    return $status_txt;
}

/**
 * 管理员角色状态
 * @author 贺强
 * @time   2021-09-14 15:14:34
 * @param integer $status 角色状态
 * @return string          返回状态描述
 */
function get_role_status($status = 0)
{
    $status_arr = [
        1 => '正常',
        4 => '禁用',
    ];
    $status_txt = $status_arr[$status] ?? '';
    return $status_txt;
}

/**
 * 获取订单支付方式
 * @param integer $type 支付方式
 * @return string        返回文字支付方式
 */
function get_pay_type($type = 0)
{
    $type_arr = [
        1 => '支付宝',
        2 => '微信',
        3 => '苹果',
        4 => '后台',
    ];
    $type_txt = $type_arr[$type] ?? '-';
    return $type_txt;
}

/**
 * App首页内容类别
 * @author 贺强
 * @time   2021-03-29 10:38:22
 * @param integer $type 内容类别
 * @return string          返回内容类别描述
 */
function get_content_type($type = 0)
{
    $type_arr = [
        1 => '精选佳作',
        2 => '猜你喜欢',
        3 => '火热连载',
        4 => '潜力新作',
        5 => '最新入库',
        6 => '最近上架',
        7 => '完本佳作',
        8 => '顶部推荐',
        9 => '主编推荐',
        10 => '优质新书',
        11 => '标新立异',
        12 => '最近新书',
    ];
    $type_txt = $type_arr[$type] ?? '-';
    return $type_txt;
}

/**
 * App首页栏目类型
 * @author 贺强
 * @time   2021-03-29 10:43:25
 * @param integer $flag 栏目类型
 * @return string          返回栏目类型描述
 */
function get_content_flag($flag = 0)
{
    $flag_arr = [
        1 => '原创',
        2 => '限免',
    ];
    $flag_txt = $flag_arr[$flag] ?? '-';
    return $flag_txt;
}

/**
 * 反馈问题类型
 * @author 贺强
 * @time   2021-03-30 18:15:17
 * @param integer $type 反馈问题类型
 * @return string          返回反馈问题类型描述
 */
function get_feedback_type($type = 0)
{
    $type_arr = [
        1 => '阅读设置',
        2 => '评论问答',
        3 => '充值问题',
        4 => '账号问题',
        5 => '其它',
    ];
    $type_txt = $type_arr[$type] ?? '-';
    return $type_txt;
}

/**
 * 把回复状态转换成文字描述
 * @author 贺强
 * @time   2021-03-30 18:24:10
 * @param integer $status 回复状态
 * @return string          返回状态描述
 */
function get_reply_status($status = 0)
{
    $status_arr = [
        0 => '否',
        1 => '是',
    ];
    $status_txt = $status_arr[$status] ?? '';
    return $status_txt;
}

/**
 * 设备类型
 * @author 贺强
 * @time   2021-03-30 18:28:53
 * @param integer $type 设备类型
 * @return string          设备类型描述
 */
function get_device_type($type = 0)
{
    $type_arr = [
        1 => 'IOS',
        2 => '安卓',
    ];
    $type_txt = $type_arr[$type] ?? '-';
    return $type_txt;
}

/**
 * 把状态转换成对错图标
 * @author 贺强
 * @time   2021-03-30 18:24:10
 * @param integer $status 状态
 * @return string          返回状态图标
 */
function get_status($status = 0)
{
    $status_arr = [
        0 => '×',
        1 => '√',
    ];
    $status_txt = $status_arr[$status] ?? '';
    return $status_txt;
}

/**
 * 举报来源
 * @author 贺强
 * @time   2021-04-06 10:54:25
 * @param integer $type 举报来源类型
 * @return string          返回举报来源描述
 */
function get_report_type($type = 0)
{
    $type_arr = [
        1 => '贴子',
        2 => '帖子评论',
        3 => '书箱评论',
    ];
    $type_txt = $type_arr[$type] ?? '';
    return $type_txt;
}

/**
 * 签约等级
 * @author 贺强
 * @time   2021-04-12 17:56:08
 * @param integer $type 签约等级
 * @return string          返回签约等级描述
 */
function get_sign_level($level = '')
{
    $level_arr = [
        'cbd' => '纯保底',
        'bdfc' => '保底分成',
        'bdjfc' => '保底加分成',
        'fdj' => '非独家',
        'dzbq' => '电子版权',
    ];
    $level_txt = $level_arr[$level] ?? '-';
    return $level_txt;
}

/**
 * 签约类型
 * @author 贺强
 * @time   2021-04-13 17:56:56
 * @param integer $type 签约类型
 * @return string          返回签约类型描述
 */
function get_sign_type($type = '')
{
    $type_arr = [
        1 => '字母签',
        2 => '保底签',
        3 => '非独家',
        4 => '电子版权',
    ];
    $type_txt = $type_arr[$type] ?? '-';
    return $type_txt;
}

/**
 * 系统消息类型
 * @author 贺强
 * @time   2021-04-19 16:47:55
 * @param integer $type 系统消息类型
 * @return string          返回系统消息类型描述
 */
function get_notice_type($type = 0)
{
    $type_arr = [
        1 => '网站公告',
        2 => '作者消息',
        3 => '用户消息',
    ];
    $type_txt = $type_arr[$type] ?? '-';
    return $type_txt;
}
